﻿
//==============================================================================
// 文件     ：linqext.cs
// 功能概要 ：list的扩展方法
//           
//           
// 作者    ：周薇
// 时间    ：2011年5月16日
// Copyright (c) 2011 重庆安运科技公司. All rights reserved.
//==============================================================================

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Linq.Expressions;
using Webcar;

namespace System.Linq
{
    public static class linqext
    {
        public static void BeginInvoke(this Action action, ISynchronizeInvoke invoker)
        {
            if (invoker.InvokeRequired)
            {
                invoker.BeginInvoke(action, null);
            }
            else
            {
                action();
            }
        }
        public static void Invoke(this Action action,ISynchronizeInvoke invoker)
        {
            if (invoker.InvokeRequired)
            {
                invoker.Invoke(action, null);
            }
            else
            {
                action();
            }
        }
        public static string Join(this IEnumerable<string> source, string seprator)
        {
            return string.Join(seprator, source.ToArray());
        }

        public static TResult MaxOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
        {
            if (source.Count() == 0) return default(TResult);
            return source.Max<TSource, TResult>(selector);
        }
        public static TResult MinOrDefault<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
        {
            if (source.Count() == 0) return default(TResult);
            return source.Min<TSource, TResult>(selector);
        }
        /// <summary>
        /// 按照条件RemoveItem
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="filter"></param>
        /// <returns></returns>
        public static int Remove<T>(this IList<T> list, Func<T, bool> filter)
        {
            List<T> ret =  list.Where(filter).ToList();
            foreach (T item in ret)
            {
                list.Remove(item);
            }
            return ret.Count();

        }
        /// <summary>
        /// Between方法扩展
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item"></param>
        /// <param name="first"></param>
        /// <param name="second"></param>
        /// <returns></returns>
        public static bool Between<T>(this T item, T first, T second) where T : IComparable
        {
            return item.CompareTo(first) >= 0 && item.CompareTo(second) <= 0;
        }
        /// <summary>
        /// NotIn
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item"></param>
        /// <param name="list"></param>
        /// <returns></returns>
        public static bool NotIn<T>(this T item, params T[] list)
        {
            return !item.In(list);
        }
        /// <summary>
        /// In
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item"></param>
        /// <param name="list"></param>
        /// <returns></returns>
        public static bool In<T>(this T item,params T[] list)
        {
            lock (list.SyncRoot)
            {
                foreach (T t in list)
                {
                    if (t.Equals(item)) return true;
                }
            }
            return false;
            //return item.In(list.AsEnumerable());
        }
        /// <summary>
        /// 线程安全的foreach
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="action"></param>
        public static void Foreach<T>(this IEnumerable<T> list, Action<T> action)
        {
            foreach (T item in list)
            {
                action(item);
            }

        }
        /// <summary>
        /// 线程安全的foreach
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="action"></param>
        public static void Foreach<T>(this IEnumerable<T> list, Action<T, int> action)
        {
            int pos = 0;
            foreach (T item in list)
            {
                action(item,pos++);
            }
        }
        /// <summary>
        /// 先执行操作，再返回自身
        /// </summary>
        public static T Do<T>(this T t, Action<T> action)
        {
            action(t);
            return t;
        }
        public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector)
        {
            return source.Distinct(Equality<T>.CreateComparer(keySelector));
        }
        public static IEnumerable<T> Distinct<T, V>(this IEnumerable<T> source, Func<T, V> keySelector, IEqualityComparer<V> comparer)
        {
            return source.Distinct(Equality<T>.CreateComparer(keySelector, comparer));
        }
    }


    public static class Equality<T>
    {
        public static IEqualityComparer<T> CreateComparer<V>(Func<T, V> keySelector)
        {
            return new CommonEqualityComparer<V>(keySelector);
        }
        public static IEqualityComparer<T> CreateComparer<V>(Func<T, V> keySelector, IEqualityComparer<V> comparer)
        {
            return new CommonEqualityComparer<V>(keySelector, comparer);
        }

        class CommonEqualityComparer<V> : IEqualityComparer<T>
        {
            private Func<T, V> keySelector;
            private IEqualityComparer<V> comparer;

            public CommonEqualityComparer(Func<T, V> keySelector, IEqualityComparer<V> comparer)
            {
                this.keySelector = keySelector;
                this.comparer = comparer;
            }
            public CommonEqualityComparer(Func<T, V> keySelector)
                : this(keySelector, EqualityComparer<V>.Default)
            { }

            public bool Equals(T x, T y)
            {
                return comparer.Equals(keySelector(x), keySelector(y));
            }
            public int GetHashCode(T obj)
            {
                return comparer.GetHashCode(keySelector(obj));
            }
        }
    }
}
